package com.hzncc.flowable_diboot.service.impl;

import cn.hutool.core.convert.NumberChineseFormatter;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.binding.Binder;
import com.diboot.core.binding.QueryBuilder;
import com.diboot.core.converter.Date2LocalDateConverter;
import com.diboot.core.holder.ThreadLocalHolder;
import com.diboot.core.util.*;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.Pagination;
import com.diboot.iam.entity.IamOrg;
import com.diboot.iam.entity.IamUser;
import com.diboot.iam.entity.IamUserPosition;
import com.diboot.iam.service.IamOrgService;
import com.diboot.iam.service.IamUserPositionService;
import com.diboot.iam.service.IamUserService;
import com.diboot.iam.util.IamSecurityUtils;
import com.diboot.tenant.entity.IamTenant;
import com.diboot.tenant.service.IamTenantService;
import com.hzncc.flowable_diboot.contract.dto.SalesContractDTO;
import com.hzncc.flowable_diboot.contract.entity.SalesContract;
import com.hzncc.flowable_diboot.contract.service.SalesContractService;
import com.hzncc.flowable_diboot.dto.*;
import com.hzncc.flowable_diboot.entity.*;
import com.hzncc.flowable_diboot.enums.MsgKey;
import com.hzncc.flowable_diboot.excel.model.DailyReportStatisticsExportModel;
import com.hzncc.flowable_diboot.mapper.*;
import com.hzncc.flowable_diboot.payment.dto.PaymentCertDTO;
import com.hzncc.flowable_diboot.payment.entity.PaymentCert;
import com.hzncc.flowable_diboot.payment.entity.PaymentContract;
import com.hzncc.flowable_diboot.payment.service.PaymentCertService;
import com.hzncc.flowable_diboot.payment.vo.PaymentCertListVO;
import com.hzncc.flowable_diboot.service.DingDingGroupService;
import com.hzncc.flowable_diboot.service.DingtalkService;
import com.hzncc.flowable_diboot.service.IReportService;
import com.hzncc.flowable_diboot.util.ConstantUtil;
import com.hzncc.flowable_diboot.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

@Log4j2
@Service
@RequiredArgsConstructor
public class ReportServiceImpl implements IReportService {

    private final CustomerMapper customerMapper;
    private final BusinessMapper businessMapper;
    private final CustomConnectorMapper customConnectorMapper;
    private final CustomerFollowRecordMapper customerFollowRecordMapper;
    private final BusinessFollowMapper businessFollowMapper;
    private final ClueFollowMapper clueFollowMapper;
    private final ClueMapper clueMapper;
    private final OppoFlowOrderMapper oppoFlowOrderMapper;
    private final IamOrgService iamOrgService;
    private final IamUserService iamUserService;
    private final EquipmentFollowMapper equipmentFollowMapper;
    private final SalesSignInMapper salesSignInMapper;
    private final DingtalkService dingtalkService;
    private final DingDingGroupService dingDingGroupService;
    private final IamUserPositionService iamUserPositionService;
    private final IamTenantService iamTenantService;
    private final SalesContractService salesContractService;
    private final PaymentCertService paymentCertService;


    /**
     * @param type 类型 y-年 m-月 d-日
     * @return
     */
    @Override
    public AchievementVO getAchievement(String type) {
        AchievementVO achievementVO = new AchievementVO();
        LocalDate begin = beginDate(type);
        LocalDate end = LocalDate.now();
        //销售合同
        SalesContractDTO salesContractDTO = new SalesContractDTO();
        salesContractDTO.setCreateTimeBegin(begin).setCreateTimeEnd(end).setPushStatus(1);
        QueryWrapper salesContractQuery = QueryBuilder.toQueryWrapper(salesContractDTO);
        List<SalesContract> salesContractList = salesContractService.getEntityList(salesContractQuery);
        BigDecimal salesContractAmount = salesContractList.stream().map(SalesContract::getFixedDiscountAmount).map(item -> StringUtils.isNotEmpty(item) ? item : "0").map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal targetAmount = salesContractAmount;
        PaymentCertDTO paymentCertDTO = new PaymentCertDTO();
        paymentCertDTO.setCreateTimeBegin(begin).setCreateTimeEnd(end).setSapPushStatus(2);
        QueryWrapper paymentCertQuery = QueryBuilder.toQueryWrapper(paymentCertDTO);
        List<PaymentCertListVO> paymentCertListVOList = Binder.convertAndBindRelations(paymentCertService.getEntityList(paymentCertQuery), PaymentCertListVO.class);
        BigDecimal receivedAmount = paymentCertListVOList.stream().map(item -> item.getPaymentRegister().getPaymentAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
//        BigDecimal receivedAmount = salesContractList.stream().map(SalesContract::getAmountReceived).map(item-> StringUtils.isNotEmpty(item)?item:"0").map(BigDecimal::new).reduce(BigDecimal.ZERO,BigDecimal::add);
        achievementVO.setTargetAmount(targetAmount)
                .setSalesContractAmount(salesContractAmount)
                .setReceivedAmount(receivedAmount)
                .setCompletionRate(new BigDecimal("0.00"));
        if (targetAmount.compareTo(new BigDecimal(0)) > 0) {
            achievementVO.setCompletionRate(receivedAmount.divide(targetAmount, 4, RoundingMode.UP).multiply(new BigDecimal(100)));
        }
        return achievementVO;
    }

    @Override
    public SalesBriefingVO getSalesBriefing(String type) {
        LocalDate begin = beginDate(type);
        LocalDate end = LocalDate.now();
        // 新增客户
        CustomerDTO customerDTO = new CustomerDTO();
        customerDTO.setCreateTimeBegin(begin);
        customerDTO.setCreateTimeEnd(end);
        Long cl = customerMapper.selectCount(QueryBuilder.toQueryWrapper(customerDTO));
        // 新增商机
        BusinessDTO businessDTO = new BusinessDTO().setCreateTimeBegin(begin).setCreateTimeEnd(end);
        Long bl = businessMapper.selectCount(QueryBuilder.toQueryWrapper(businessDTO));
        // 新增联系人
        CustomConnectorDTO customConnectorDTO = new CustomConnectorDTO().setCreateTimeBegin(begin).setCreateTimeEnd(end);
        Long ccl = customConnectorMapper.selectCount(QueryBuilder.toQueryWrapper(customConnectorDTO));
        // 新增跟进记录
        CustomerFollowRecordDTO customerFollowRecordDTO = new CustomerFollowRecordDTO().setCreateTimeBegin(begin).setCreateTimeEnd(end);
        Long f1 = customerFollowRecordMapper.selectCount(QueryBuilder.toQueryWrapper(customerFollowRecordDTO));
        BusinessFollowDTO businessFollowDTO = new BusinessFollowDTO().setCreateTimeBegin(begin).setCreateTimeEnd(end);
        Long f2 = businessFollowMapper.selectCount(QueryBuilder.toQueryWrapper(businessFollowDTO));
        ClueFollowDTO clueFollowDTO = new ClueFollowDTO().setCreateTimeBegin(begin).setCreateTimeEnd(end);
        Long f3 = clueFollowMapper.selectCount(QueryBuilder.toQueryWrapper(clueFollowDTO));
        // 新增线索
        ClueDTO clueDTO = new ClueDTO().setCreateTimeBegin(begin).setCreateTimeEnd(end);
        Long ll = clueMapper.selectCount(QueryBuilder.toQueryWrapper(clueDTO));
        // 阶段变化的商机
        // 修改时间在目标时间范围内 且状态发生变化的商机流程
        OppoFlowOrderDTO oppoFlowOrderDTO = new OppoFlowOrderDTO().setUpdateTimeBegin(begin).setUpdateTimeEnd(end);
        QueryWrapper queryWrapper = QueryBuilder.toQueryWrapper(oppoFlowOrderDTO);
        queryWrapper.in("status", "going", "over");
        Long ol = oppoFlowOrderMapper.selectCount(queryWrapper);
        // 新增合同
        SalesContractDTO salesContractDTO = new SalesContractDTO();
        salesContractDTO.setCreateTimeBegin(begin).setCreateTimeEnd(end);
        Long scCount = salesContractService.getMapper().selectCount(QueryBuilder.toQueryWrapper(salesContractDTO));
        // 新增回款
        PaymentCertDTO paymentCertDTO = new PaymentCertDTO();
        paymentCertDTO.setCreateTimeBegin(begin).setCreateTimeEnd(end);
        Long certCount = paymentCertService.getMapper().selectCount(QueryBuilder.toQueryWrapper(paymentCertDTO));
        return new SalesBriefingVO()
                .setNewCustomerNum(cl)
                .setNewBusinessNum(bl)
                .setNewContactNum(ccl)
                .setNewFollowNum(f1 + f2 + f3)
                .setNewLeadNum(ll)
                .setStageChangeBusiness(ol)
                .setNewContractNum(scCount) // 合同
                .setNewCollectionNum(certCount); // 回款
    }

    /**
     * 获取时间范围
     *
     * @param type 类型 y-年 m-月 d-日
     * @return
     * @author 陈广煜
     * @date 2024/7/2
     */
    private LocalDate beginDate(String type) {
        Date2LocalDateConverter converter = new Date2LocalDateConverter();
        String beginFmtStr;
        switch (type) {
            case "y":
                beginFmtStr = "yyyy-01-01 00:00:00";
                break;
            case "m":
                beginFmtStr = "yyyy-MM-01 00:00:00";
                break;
            case "d":
                beginFmtStr = "yyyy-MM-dd 00:00:00";
                break;
            default:
                beginFmtStr = "";
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(beginFmtStr);
        String format = simpleDateFormat.format(new Date());
        Date date = null;
        try {
            date = simpleDateFormat.parse(format);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        return converter.convert(date);
    }


    /**
     * 签到报表
     *
     * @return
     * @author 陈广煜
     * @date 2024/7/8
     */
    @Override
    public List<DailyReport> checkInReport(LocalDate begin, LocalDate end, String name, Pagination pagination) {
        // 获取报表人员 (销售部)
        List<String> empIds = personnelInNeedOfStatistics("dept", ConstantUtil.DEPT_SALES);
        if (empIds == null || empIds.isEmpty()) return null;
        List<FollowVO> followVOS = new ArrayList<>();
        //List<IamUser> users = iamUserService.getEntityListByIds(empIds);
        QueryWrapper<IamUser> uqw = new QueryWrapper<>();
        uqw.lambda().in(IamUser::getId, empIds);
        if (S.isNotBlank(name)) {
            uqw.lambda().like(IamUser::getRealname, name);
        }
        List<IamUser> users = iamUserService.getEntityList(uqw, pagination);
        empIds = BeanUtils.collectToList(users, IamUser::getId);
        for (IamUser user : users) {
            FollowVO follow = new FollowVO();
            follow.setUid(user.getId());
            follow.setName(user.getRealname());
            follow.setFollowTime(LocalDateTime.now());
            followVOS.add(follow);
        }
        // 查询 签到信息
        QueryWrapper<SalesSignIn> wrapper = QueryBuilder.toQueryWrapper(new SalesSignInDTO().setSignInTimeBegin(begin).setSignInTimeEnd(end));
        wrapper.lambda().in(SalesSignIn::getUid, empIds);
        List<SalesSignIn> salesSignIns = salesSignInMapper.selectList(wrapper);
        List<SalesSignInListVO> salesSignInListVOS = Binder.convertAndBindRelations(salesSignIns, SalesSignInListVO.class);
        // 数据格式处理
        List<FollowVO> fs = convertSignIn(salesSignInListVOS);
        if (!fs.isEmpty()) {
            followVOS.addAll(fs);
        }
        for (FollowVO followVO : followVOS) {
            followVO.setDate(followVO.getFollowTime().toLocalDate());
        }
        return pageView(followVOS);
    }

    @Override
    public void sendRobotMsg(Object type) throws Exception {
        // 获取租户
        //QueryWrapper<IamTenant> queryWrapper = new QueryWrapper<>();
        //List<IamTenant> tenants = tenantService.getEntityList(queryWrapper);
        // 获取群id
        ThreadLocalHolder.setIgnoreInterceptor();
        QueryWrapper<DingDingGroup> qw = new QueryWrapper<>();
        List<DingDingGroup> groups = dingDingGroupService.getEntityList(qw);
        //Map<String, List<DingDingGroup>> groupByTenant = groups.stream().collect(Collectors.groupingBy(DingDingGroup::getTenantId));
        if (groups.isEmpty()) {
            return;
        }
        List<DingDingGroup> delList = new ArrayList<>();
        for (DingDingGroup group : groups) {
            // 查询日报
            String s = genDailyReportSimpleText(group.getOrgId(), type, group.getTenantId());
            log.info("发送日报:" + s);
            if (S.isEmpty(s)) {
                continue;
            }
            JsonResult<String> token = dingtalkService.getToken(group.getTenantId());
            if (token.getCode() != 0) {
                throw new RuntimeException("获取token失败:" + token.getMsg());
            }
            // 发送消息
            JsonResult<String> result = dingtalkService.sendRobotMessage(token.getData(), group.getOpenConversationId(), s, MsgKey.TEXT.getKey());
            if (result.getCode() == -1 && S.equals(result.getData(), "invalid.openConversationId")) {
                group.setDeleted(true);
                delList.add(group);
            }
        }
        dingDingGroupService.deleteEntities(delList);
    }

    /**
     * 统计报表
     *
     * @param begin
     * @param end
     * @param name
     * @param pagination
     * @return
     */
    @Override
    public List<DailyReport> statisticalReport(LocalDate begin, LocalDate end, String name, Pagination pagination) {
        // 获取报表人员 (销售部)
        List<String> empIds = personnelInNeedOfStatistics("dept", ConstantUtil.DEPT_SALES);
        if (empIds == null || empIds.isEmpty()) return null;
        List<FollowVO> followVOS = new ArrayList<>();
        //List<IamUser> users = iamUserService.getEntityListByIds(empIds);
        QueryWrapper<IamUser> uqw = new QueryWrapper<>();
        uqw.lambda().in(IamUser::getId, empIds);
        if (S.isNotBlank(name)) {
            uqw.lambda().like(IamUser::getRealname, name);
        }
        List<IamUser> users = iamUserService.getEntityList(uqw, pagination);
        empIds = BeanUtils.collectToList(users, IamUser::getId);
        for (IamUser user : users) {
            FollowVO follow = new FollowVO();
            follow.setUid(user.getId());
            follow.setName(user.getRealname());
            follow.setFollowTime(LocalDateTime.now());
            follow.setUserNum(user.getUserNum());
            followVOS.add(follow);
        }
        getFollowVO(followVOS, empIds, begin, end, false);
        // 处理数据结构
        for (FollowVO followVO : followVOS) {
            followVO.setDate(followVO.getFollowTime().toLocalDate());
        }
        return pageViewStatistics(followVOS);
    }

    @Override
    public void sendRobotExcelMsg(String type) throws Exception {
        ThreadLocalHolder.setIgnoreInterceptor();
        QueryWrapper<DingDingGroup> qw = new QueryWrapper<>();
        List<DingDingGroup> groups = dingDingGroupService.getEntityList(qw);
        //Map<String, List<DingDingGroup>> groupByTenant = groups.stream().collect(Collectors.groupingBy(DingDingGroup::getTenantId));
        if (groups.isEmpty()) {
            return;
        }
        List<DingDingGroup> delList = new ArrayList<>();
        for (DingDingGroup group : groups) {
            // 查询日报
            String file = genDailyReportStatistics(group.getTenantId(), group.getOrgId(), type);
            if (S.isEmpty(file)) {
                continue;
            }
            // 发送消息
            JsonResult<String> result = dingtalkService.sendRobotMessage(group.getOpenConversationId(), file, MsgKey.SAMPLE_FILE.getKey());
            if (result.getCode() == -1 && S.equals(result.getData(), "invalid.openConversationId")) {
                group.setDeleted(true);
                delList.add(group);
            }
        }
        dingDingGroupService.deleteEntities(delList);
    }

    /**
     * 获取群组（部门） 日报
     *
     * @param dept 部门
     * @return
     * @author 陈广煜
     * @date 2024/7/11
     */
    private String genDailyReport(String dept, Object type) {
        // 获取报表人员
        List<String> empIds = getDeptAndSubEmp(dept);
        if (empIds.isEmpty()) return null;
        List<FollowVO> followVOS = new ArrayList<>();
        //List<IamUser> users = iamUserService.getEntityListByIds(empIds);
        QueryWrapper<IamUser> uqw = new QueryWrapper<>();
        uqw.lambda().in(IamUser::getId, empIds);
        ThreadLocalHolder.setIgnoreInterceptor();
        List<IamUser> users = iamUserService.getEntityList(uqw);
        empIds = BeanUtils.collectToList(users, IamUser::getId);
        for (IamUser user : users) {
            FollowVO follow = new FollowVO();
            follow.setUid(user.getId());
            follow.setName(user.getRealname());
            follow.setFollowTime(LocalDateTime.now());
            follow.setUserNum(user.getUserNum());
            followVOS.add(follow);
        }
        // 查询跟进
        LocalDate begin = LocalDate.now();
        LocalDate end = LocalDate.now().plusDays(1);
        if (S.equals(toStr(type, ""), "yesterday")) {
            begin = LocalDate.now().minusDays(1);
            end = LocalDate.now();
        }
        getFollowVO(followVOS, empIds, begin, end, true);
        // 数据处理
        Map<String, String> msg = new HashMap<>();
        msg.put("title", begin.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "日报");
        Map<String, List<FollowVO>> collect = followVOS.stream().collect(Collectors.groupingBy(FollowVO::getUid));
        Set<String> uidSet = collect.keySet();
        JdbcTemplate jdbcTemplate = SqlExecutor.getJdbcTemplate();
        Map<String, String> orgMap = new HashMap<>();
        jdbcTemplate.query("select o.name,u.id from dbt_iam_org o , dbt_iam_user u where u.id in ('" + S.join(uidSet, "','") + "') and o.id = u.org_id", res -> {
            orgMap.put(res.getString("id"), res.getString("name"));
        });
        Map<String, String> map = new HashMap<>();
        String unWrite = "**%s未填写**";
        StringBuilder unWriteMember = new StringBuilder();
        for (Map.Entry<String, List<FollowVO>> entry : collect.entrySet()) {
            StringBuilder member = new StringBuilder("**" + entry.getValue().get(0).getName() + ":** \n");
            StringBuilder content = new StringBuilder();
            StringBuilder businessFollow = new StringBuilder("商务跟进\n");
            boolean flag = false;
            for (FollowVO followVO : entry.getValue()) {
                if (followVO.getContent() == null) continue;
                if (S.contains("其他商务", followVO.getType())) {
                    businessFollow.append(followVO.getContent().replaceAll("\n", " \n")).append("\n\n");
                    flag = true;
                } else {
                    String line = followVO.getType() + "\n" + followVO.getContent().replaceAll("\n", " \n");
                    content.append(line).append(line.endsWith("\n") ? "\n" : "\n\n");
                }
            }
            member.append(content);
            if (flag) {
                member.append(businessFollow);
            }
            String s = map.get(orgMap.get(entry.getKey()));
            if (s == null) {
                s = "";
            }
            if (entry.getValue().stream().allMatch(f -> f.getContent() == null || f.getContent().isEmpty())) {
                unWriteMember.append(entry.getValue().get(0).getName()).append("、");
                continue;
            }
            map.put(orgMap.get(entry.getKey()), s + member);
        }
        StringBuilder text = new StringBuilder("### " + msg.get("title") + "\n");
        for (Map.Entry<String, String> orgEntry : map.entrySet()) {
            text.append("#### ").append(orgEntry.getKey()).append(":\n").append(orgEntry.getValue()).append("\n");
        }
        if (!unWriteMember.isEmpty()) {
            text = new StringBuilder(text.substring(0, text.lastIndexOf("\n")));
            text.append(unWrite.formatted(unWriteMember.substring(0, unWriteMember.length() - 1)));
        }
        msg.put("text", text.toString());
        return JSON.stringify(msg);
    }

    /**
     * 获取群组（部门） 日报
     *
     * @param dept 部门
     * @return
     * @author 陈广煜
     * @date 2024/7/11
     */
    private String genDailyReportSimpleText(String dept, Object type, String tenant) {
        // 获取租户
        IamTenant tenantEntity = iamTenantService.getEntity(tenant);
        // 获取报表人员
        List<String> empIds = getDeptAndSubEmp(dept);
        if (empIds.isEmpty()) return null;
        List<FollowVO> followVOS = new ArrayList<>();
        //List<IamUser> users = iamUserService.getEntityListByIds(empIds);
        QueryWrapper<IamUser> uqw = new QueryWrapper<>();
        uqw.lambda().in(IamUser::getId, empIds);
        ThreadLocalHolder.setIgnoreInterceptor();
        List<IamUser> users = iamUserService.getEntityList(uqw);
        empIds = BeanUtils.collectToList(users, IamUser::getId);
        for (IamUser user : users) {
            FollowVO follow = new FollowVO();
            follow.setUid(user.getId());
            follow.setName(user.getRealname());
            follow.setFollowTime(LocalDateTime.now());
            follow.setUserNum(user.getUserNum());
            followVOS.add(follow);
        }
        // 查询跟进
        LocalDate begin = LocalDate.now();
        LocalDate end = LocalDate.now().plusDays(1);
        if (S.equals(toStr(type, ""), "yesterday")) {
            begin = LocalDate.now().minusDays(1);
            end = LocalDate.now();
        }
        getFollowVO(followVOS, empIds, begin, end, true);
        // 数据处理
        Map<String, String> msg = new HashMap<>();
//        msg.put("title", begin.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "日报");
        Map<String, List<FollowVO>> collect = followVOS.stream().collect(Collectors.groupingBy(FollowVO::getUid));
        Set<String> uidSet = collect.keySet();
        JdbcTemplate jdbcTemplate = SqlExecutor.getJdbcTemplate();
        Map<String, String> orgMap = new HashMap<>();
        jdbcTemplate.query("select o.name,u.id from dbt_iam_org o , dbt_iam_user u where u.id in ('" + S.join(uidSet, "','") + "') and o.id = u.org_id", res -> {
            orgMap.put(res.getString("id"), res.getString("name") != null ? res.getString("name").replaceAll(":", "") : "");
        });
        Map<String, String> map = new HashMap<>();
        String unWrite = "%s未填写";
        StringBuilder unWriteMember = new StringBuilder();
        for (Map.Entry<String, List<FollowVO>> entry : collect.entrySet()) {
            StringBuilder member = new StringBuilder(orgMap.get(entry.getKey()) + " - " + entry.getValue().get(0).getName() + ":\n");
            StringBuilder content = new StringBuilder();
            StringBuilder businessFollow = new StringBuilder();
            boolean flag = false;
            int cusIndex = 0;
            int busIndex = 0;
            for (FollowVO followVO : entry.getValue()) {
                // 跟进序号
                String cusNo = NumberChineseFormatter.format(cusIndex++, false);
                String busNo = NumberChineseFormatter.format(busIndex++, false);
                String contentText = followVO.getContent();
                if (contentText == null) continue;
                // 去除开头的空行
                if (contentText.startsWith("\n")) {
                    contentText = contentText.substring(1);
                }
                if (S.contains("其他商务", followVO.getType())) {
                    businessFollow.append(busNo).append("、商务跟进\n").append(contentText.replaceAll("\n", " \n")).append("\n\n");
                    flag = true;
                } else {
                    String line = cusNo + "、" + followVO.getType() + "\n" + contentText.replaceAll("\n", " \n");
                    content.append(line).append(line.endsWith("\n") ? "\n" : "\n\n");
                }
            }
            member.append(content);
            if (flag) {
                member.append(businessFollow);
            }
            String s = map.get(orgMap.get(entry.getKey()));
            if (s == null) {
                s = "";
            }
            if (entry.getValue().stream().allMatch(f -> f.getContent() == null || f.getContent().isEmpty())) {
                unWriteMember.append(entry.getValue().get(0).getName()).append("、");
                continue;
            }
            map.put(orgMap.get(entry.getKey()), s + member);
        }
        StringBuilder text = new StringBuilder(begin.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "日报 - " + tenantEntity.getName() + "\n");
        for (Map.Entry<String, String> orgEntry : map.entrySet()) {
            text.append(orgEntry.getKey()).append(":\n").append(orgEntry.getValue()).append("\n");
        }
        if (!unWriteMember.isEmpty()) {
            text = new StringBuilder(text.substring(0, text.lastIndexOf("\n")));
            text.append(unWrite.formatted(unWriteMember.substring(0, unWriteMember.length() - 1)));
        }
        // 添加文本 并去除多余的空行
        msg.put("content", text.toString().replaceAll("\n\n\n", "\n\n"));
        return JSON.stringify(msg);
    }

    /**
     * 查询处理跟进信息
     *
     * @param followVOS
     * @param empIds
     * @param begin
     * @param end
     * @author 陈广煜
     * @date 2024/7/11
     */
    private void getFollowVO(List<FollowVO> followVOS, List<String> empIds, LocalDate begin, LocalDate end, boolean ignore) {
        if (followVOS == null) {
            followVOS = new ArrayList<>();
        }
        QueryWrapper<CustomerFollowRecord> wrapper = QueryBuilder.toQueryWrapper(new CustomerFollowRecordDTO()
                .setFollowTimeBegin(begin).setFollowTimeEnd(end));
        wrapper.lambda().in(CustomerFollowRecord::getUserId, empIds);
        if (ignore) {
            ThreadLocalHolder.setIgnoreInterceptor();
        }
        List<CustomerFollowRecord> records = customerFollowRecordMapper.selectList(wrapper);
        List<CustomerFollowRecordListVO> vos = Binder.convertAndBindRelations(records, CustomerFollowRecordListVO.class);
        List<FollowVO> cus = convertCusFollow(vos);
        if (!cus.isEmpty()) {
            followVOS.addAll(cus);
        }
        // 查询线索跟进
        QueryWrapper<ClueFollow> w = QueryBuilder.toQueryWrapper(new ClueFollowDTO().setFollowTimeBegin(begin).setFollowTimeEnd(end));
        w.lambda().in(ClueFollow::getFollower, empIds);
        if (ignore) {
            ThreadLocalHolder.setIgnoreInterceptor();
        }
        List<ClueFollow> clueFollows = clueFollowMapper.selectList(w);
        List<ClueFollowListVO> clueFollowListVOS = Binder.convertAndBindRelations(clueFollows, ClueFollowListVO.class);
        List<FollowVO> clu = convertClueFollow(clueFollowListVOS);
        if (!clu.isEmpty()) {
            followVOS.addAll(clu);
        }
        // 查询商机跟进
        QueryWrapper<BusinessFollow> bw = QueryBuilder.toQueryWrapper(new BusinessFollowDTO().setFollowTimeBegin(begin).setFollowTimeEnd(end));
        bw.lambda().in(BusinessFollow::getUid, empIds);
        if (ignore) {
            ThreadLocalHolder.setIgnoreInterceptor();
        }
        List<BusinessFollow> businessFollows = businessFollowMapper.selectList(bw);
        List<BusinessFollowListVO> bindRelations = Binder.convertAndBindRelations(businessFollows, BusinessFollowListVO.class);
        List<FollowVO> bus = convertBusFollow(bindRelations);
        if (!bus.isEmpty()) {
            followVOS.addAll(bus);
        }
        // 查询设备跟进
        QueryWrapper<EquipmentFollow> ew = QueryBuilder.toQueryWrapper(new EquipmentFollowDTO().setFollowTimeBegin(begin).setFollowTimeEnd(end));
        ew.lambda().in(EquipmentFollow::getCreateBy, empIds);
        if (ignore) {
            ThreadLocalHolder.setIgnoreInterceptor();
        }
        List<EquipmentFollow> equipmentFollows = equipmentFollowMapper.selectList(ew);
        List<EquipmentFollowListVO> equipmentFollowListVOS = Binder.convertAndBindRelations(equipmentFollows, EquipmentFollowListVO.class);
        List<FollowVO> equipmentFollow = convertEquipmentFollow(equipmentFollowListVOS);
        if (!bus.isEmpty()) {
            followVOS.addAll(equipmentFollow);
        }
    }


    /**
     * 签到数据初处理
     *
     * @param list
     * @return
     * @author 陈广煜
     * @date 2024/7/9
     */
    private List<FollowVO> convertSignIn(List<SalesSignInListVO> list) {
        List<FollowVO> followVOS = new ArrayList<>();
        for (SalesSignInListVO salesSignIn : list) {
            FollowVO follow = new FollowVO();
            follow.setType(salesSignIn.getPlace());
            follow.setContent(salesSignIn.getRemark());
            follow.setFollowTime(salesSignIn.getSignInTime());
            follow.setName(salesSignIn.getUidLabel());
            follow.setUid(salesSignIn.getUid());
            followVOS.add(follow);
        }
        return followVOS;
    }


    /**
     * 日报报表
     *
     * @return
     * @author 陈广煜
     * @date 2024/7/8
     */
    @Override
    public List<DailyReport> dailyReport(LocalDate begin, LocalDate end, String name, Pagination pagination) {
        // 获取报表人员
        List<String> empIds = personnelInNeedOfStatistics("dept", ConstantUtil.DEPT_SALES);
        if (empIds == null || empIds.isEmpty()) return Collections.emptyList();
        List<FollowVO> followVOS = new ArrayList<>();
        //List<IamUser> users = iamUserService.getEntityListByIds(empIds);
        QueryWrapper<IamUser> uqw = new QueryWrapper<>();
        uqw.lambda().in(IamUser::getId, empIds);
        if (S.isNotBlank(name)) {
            uqw.lambda().like(IamUser::getRealname, name);
        }
        List<IamUser> users = iamUserService.getEntityList(uqw, pagination);
        empIds = BeanUtils.collectToList(users, IamUser::getId);
        for (IamUser user : users) {
            FollowVO follow = new FollowVO();
            follow.setUid(user.getId());
            follow.setName(user.getRealname());
            follow.setFollowTime(LocalDateTime.now());
            follow.setUserNum(user.getUserNum());
            followVOS.add(follow);
        }
        getFollowVO(followVOS, empIds, begin, end, false);
        // 处理数据结构
        for (FollowVO followVO : followVOS) {
            followVO.setDate(followVO.getFollowTime().toLocalDate());
        }
        return pageView(followVOS);
    }

    /**
     * 报表需要统计的人员
     *
     * @return
     * @author 陈广煜
     * @date 2024-08-15
     */
    private List<String> personnelInNeedOfStatistics(String type, String dept) {
        List<String> empIds = new ArrayList<>();
        if (S.equals(type, "dept")) {
            QueryWrapper<IamOrg> qw = new QueryWrapper<>();
            qw.lambda().eq(IamOrg::getName, dept);
            IamOrg org = iamOrgService.getSingleEntity(qw);
            if (org == null) {
                return null;
            }
            empIds = getDeptAndSubEmp(org.getId());
        } else {
            QueryWrapper<IamUser> qw = new QueryWrapper<>();
            qw.lambda().select(IamUser::getId).ne(IamUser::getUserNum, "admin");
            List<IamUser> entityList = iamUserService.getEntityList(qw);
            empIds = BeanUtils.collectToList(entityList, IamUser::getId);
        }
        List<String> manager = getManager();
        if (manager != null && !manager.isEmpty()) {
            if (empIds.isEmpty()) {
                empIds = new ArrayList<>();
            }
            empIds.addAll(manager);
        }
        empIds.sort(String::compareTo);
        return empIds;
    }


    /**
     * 获取部门及下级部门员工id
     *
     * @param orgId
     * @return
     * @author 陈广煜
     * @date 2024/5/31
     */
    private List<String> getDeptAndSubEmp(String orgId) {
        ThreadLocalHolder.setIgnoreInterceptor();
        List<String> childOrgIds = getChildOrgIds(Arrays.asList(orgId));
        if (childOrgIds == null || childOrgIds.isEmpty()) {
            childOrgIds = new ArrayList<>();
        }
        childOrgIds.add(orgId);
        QueryWrapper<IamUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("org_id", childOrgIds);
        QueryWrapper<IamUserPosition> upqw = new QueryWrapper<>();
        upqw.lambda().in(IamUserPosition::getOrgId, childOrgIds);
        ThreadLocalHolder.setIgnoreInterceptor();
        List<String> userIds = iamUserPositionService.getValuesOfField(upqw, IamUserPosition::getUserId);
        if (userIds != null && !userIds.isEmpty()) {
            queryWrapper.or().in("id", userIds);
        }
        ThreadLocalHolder.setIgnoreInterceptor();
        List<IamUser> entityList = iamUserService.getEntityList(queryWrapper);
        return BeanUtils.collectToList(entityList, IamUser::getId);
    }

    public List<String> getChildOrgIds(List<String> orgIds) {
        QueryWrapper<IamOrg> qw = new QueryWrapper<>();
        qw.lambda().in(IamOrg::getParentId, orgIds);
        ThreadLocalHolder.setIgnoreInterceptor();
        List<IamOrg> orgs = iamOrgService.getEntityList(qw);
        List<String> list = BeanUtils.collectToList(orgs, IamOrg::getId);
        if (!orgs.isEmpty()) {
            List<String> childOrgIds = getChildOrgIds(BeanUtils.collectToList(orgs, IamOrg::getId));
            if (!childOrgIds.isEmpty()) {
                list.addAll(childOrgIds);
            }
        }
        return list;
    }

    /**
     * 数据格式转换
     *
     * @param records
     * @return
     * @author 陈广煜
     * @date 2024/7/8
     */
    private List<FollowVO> convertCusFollow(List<CustomerFollowRecordListVO> records) {
        List<FollowVO> list = new ArrayList<>();
        for (CustomerFollowRecordListVO record : records) {
            FollowVO vo = new FollowVO();
            vo.setUid(record.getUserId());
            vo.setName(record.getUserIdLabel());
            vo.setFollowTime(record.getFollowTime());
            vo.setContent(record.getContent());
            Boolean otherActive = record.getOtherActive();
            vo.setType(otherActive ? "其他商务" : ("客户跟进 - " + record.getCustomerName()));
            list.add(vo);
        }
        return list;
    }

    /**
     * 数据格式转换
     *
     * @param records
     * @return
     * @author 陈广煜
     * @date 2024/7/8
     */
    private List<FollowVO> convertClueFollow(List<ClueFollowListVO> records) {
        List<FollowVO> list = new ArrayList<>();
        for (ClueFollowListVO record : records) {
            FollowVO vo = new FollowVO();
            vo.setUid(record.getFollower());
            vo.setName(record.getFollowerLabel());
            vo.setFollowTime(record.getFollowTime());
            vo.setContent(record.getContent());
            Boolean otherActive = record.getOtherActive();
            vo.setType(otherActive ? "其他商务" : "线索跟进");
            list.add(vo);
        }
        return list;
    }

    /**
     * 数据格式转换
     *
     * @param records
     * @return
     * @author 陈广煜
     * @date 2024/7/8
     */
    private List<FollowVO> convertBusFollow(List<BusinessFollowListVO> records) {
        List<FollowVO> list = new ArrayList<>();
        for (BusinessFollowListVO record : records) {
            FollowVO vo = new FollowVO();
            vo.setUid(record.getUid());
            vo.setName(record.getUidLabel());
            vo.setFollowTime(record.getFollowTime());
            vo.setContent(record.getContent());
            Boolean otherActive = record.getOtherActive();
            vo.setType(otherActive ? "其他商务" : "商机跟进");
            list.add(vo);
        }
        return list;
    }

    /**
     * 数据格式转换
     *
     * @param records
     * @return
     * @author 陈广煜
     * @date 2024/7/8
     */
    private List<FollowVO> convertEquipmentFollow(List<EquipmentFollowListVO> records) {
        List<FollowVO> list = new ArrayList<>();
        for (EquipmentFollowListVO record : records) {
            FollowVO vo = new FollowVO();
            vo.setUid(record.getCreateBy());
            vo.setName(record.getCreateByLabel());
            vo.setFollowTime(record.getFollowTime());
            vo.setContent(record.getDetails());
            Long businessActivities = record.getBusinessActivities();
            vo.setType(businessActivities == 1 ? "其他商务" : "设备跟进");
            list.add(vo);
        }
        return list;
    }

    /**
     * 页面展示数据格式处理
     *
     * @param list
     * @return
     * @author 陈广煜
     * @date 2024/7/8
     */
    private List<DailyReport> pageView(List<FollowVO> list) {
        Map<String, List<FollowVO>> groupByUid = list.stream().collect(Collectors.groupingBy(FollowVO::getUid));
        List<DailyReport> result = new ArrayList<>();
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm:ss");
        for (Map.Entry<String, List<FollowVO>> entry : groupByUid.entrySet()) {
            DailyReport report = new DailyReport();
            List<FollowVO> value = entry.getValue();
            if (value.isEmpty()) {
                continue;
            }
            report.setName(value.get(0).getName());
            Map<LocalDate, List<FollowVO>> groupByTime = value.stream().collect(Collectors.groupingBy(FollowVO::getDate));
            for (Map.Entry<LocalDate, List<FollowVO>> en : groupByTime.entrySet()) {
                List<FollowVO> vos = en.getValue();
                LocalDate key = en.getKey();
                DayOfWeek dayOfWeek = key.getDayOfWeek();
                List<String> details = vos.stream().filter(e -> e.getContent() != null).map(e -> e.getFollowTime().format(fmt) + "--" + e.getType() + "--" + e.getContent()).collect(Collectors.toList());
                String str = S.join(details, "\n");
                exeDayOfWeek(report, dayOfWeek, str);
            }
            nullDataProcess(result, report, "");
        }
        return result;
    }

    /**
     * 页面展示数据格式处理
     *
     * @param list
     * @return
     * @author 陈广煜
     * @date 2024/7/8
     */
    private List<DailyReport> pageViewStatistics(List<FollowVO> list) {
        Map<String, List<FollowVO>> groupByUid = list.stream().collect(Collectors.groupingBy(FollowVO::getUid));
        List<DailyReport> result = new ArrayList<>();
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm:ss");
        for (Map.Entry<String, List<FollowVO>> entry : groupByUid.entrySet()) {
            DailyReport report = new DailyReport();
            List<FollowVO> value = entry.getValue();
            if (value.isEmpty()) {
                continue;
            }
            report.setName(value.get(0).getName());
            Map<LocalDate, List<FollowVO>> groupByTime = value.stream().collect(Collectors.groupingBy(FollowVO::getDate));
            for (Map.Entry<LocalDate, List<FollowVO>> en : groupByTime.entrySet()) {
                List<FollowVO> vos = en.getValue();
                LocalDate key = en.getKey();
                DayOfWeek dayOfWeek = key.getDayOfWeek();
                List<String> details = vos.stream().filter(e -> e.getContent() != null).map(e -> e.getFollowTime().format(fmt) + "--" + e.getType() + "--" + e.getContent()).collect(Collectors.toList());
                String str = String.valueOf(details.size()).equals("0") ? null : String.valueOf(details.size());
                exeDayOfWeek(report, dayOfWeek, str);
            }
            nullDataProcess(result, report, "❌");
        }
        return result;
    }

    /**
     * 处理每日报告中的空数据。
     * 将每日报告中的各天数据转换为字符串格式，并添加到结果列表中。
     * 这样做的目的是为了统一报告中的数据格式，确保即使原始数据为null，也能以字符串形式呈现，避免后续处理中的空指针异常。
     *
     * @param result 存储处理后报告的列表，添加处理后的报告到此列表。
     * @param report 需要处理的每日报告对象，其中的每天数据将被转换为字符串格式。
     */
    private void nullDataProcess(List<DailyReport> result, DailyReport report, String defaultValue) {
        // 将星期五的数据转换为字符串
        report.setFri(toStr(report.getFri(), defaultValue));
        // 将星期一的数据转换为字符串
        report.setMon(toStr(report.getMon(), defaultValue));
        // 将星期四的数据转换为字符串
        report.setThu(toStr(report.getThu(), defaultValue));
        // 将星期三的数据转换为字符串
        report.setWed(toStr(report.getWed(), defaultValue));
        // 将星期日的数据转换为字符串
        report.setSun(toStr(report.getSun(), defaultValue));
        // 将星期六的数据转换为字符串
        report.setSat(toStr(report.getSat(), defaultValue));
        // 将星期二的数据转换为字符串
        report.setTue(toStr(report.getTue(), defaultValue));
        // 将处理后的报告添加到结果列表
        result.add(report);
    }


    /**
     * 根据指定的weekday，为每日报告的特定字段赋值。
     * 此方法通过switch-case语句结构，根据传入的DayOfWeek对象，选择对应的字段并赋值。
     * 这种设计允许报告针对一周中的不同日子有特定的字段值，从而支持更细化的报告定制。
     *
     * @param report    日报对象，用于存储特定星期几的字段值。
     * @param dayOfWeek 指定的星期几，用于确定要设置的字段。
     * @param str       要设置的字段值，此值将根据指定的星期几被赋给相应的字段。
     */
    private void exeDayOfWeek(DailyReport report, DayOfWeek dayOfWeek, String str) {
        switch (dayOfWeek) {
            case MONDAY:
                report.setMon(str);
                break;
            case THURSDAY:
                report.setThu(str);
                break;
            case WEDNESDAY:
                report.setWed(str);
                break;
            case TUESDAY:
                report.setTue(str);
                break;
            case FRIDAY:
                report.setFri(str);
                break;
            case SATURDAY:
                report.setSat(str);
                break;
            case SUNDAY:
                report.setSun(str);
                break;
        }
    }


    private String toStr(Object obj, String defaultValue) {
        return Optional.ofNullable(obj).orElse(defaultValue).toString();
    }


    /**
     * 统计报表
     *
     * @param dept
     * @param type
     * @author 陈广煜
     * @date 2024-07-29
     */
    public String genDailyReportStatistics(String tenant, String dept, Object type) throws IOException {
        // 获取报表人员 (销售部)
        QueryWrapper<IamOrg> qw = new QueryWrapper<>();
        qw.lambda().eq(IamOrg::getName, ConstantUtil.DEPT_SALES);
        ThreadLocalHolder.setIgnoreInterceptor();
        IamOrg org = iamOrgService.getEntity(dept);
        if (org == null) {
            return null;
        }
        List<String> empIds = getDeptAndSubEmp(org.getId());
        if (empIds.isEmpty()) return null;
        List<FollowVO> followVOS = new ArrayList<>();
        //List<IamUser> users = iamUserService.getEntityListByIds(empIds);
        QueryWrapper<IamUser> uqw = new QueryWrapper<>();
        uqw.lambda().in(IamUser::getId, empIds);
        ThreadLocalHolder.setIgnoreInterceptor();
        List<IamUser> users = iamUserService.getEntityList(uqw);
        empIds = BeanUtils.collectToList(users, IamUser::getId);
        for (IamUser user : users) {
            FollowVO follow = new FollowVO();
            follow.setUid(user.getId());
            follow.setName(user.getRealname());
            follow.setFollowTime(LocalDateTime.now());
            follow.setUserNum(user.getUserNum());
            followVOS.add(follow);
        }
        List<LocalDate> weekDate = weekDate(LocalDate.now());
        LocalDate begin = weekDate.get(0);
        LocalDate end = weekDate.get(6);
        if (S.equals(toStr(type, ""), "lastWeek")) {
            begin = begin.minusWeeks(1);
            end = end.minusWeeks(1);
        }
        getFollowVO(followVOS, empIds, begin, end, true);
        // 处理数据结构
        for (FollowVO followVO : followVOS) {
            followVO.setDate(followVO.getFollowTime().toLocalDate());
        }
        List<DailyReport> reports = pageViewStatistics(followVOS);
        String filePath = createExcel(reports);
        Map<String, String> map = new HashMap<>();
        try {
            JsonResult<String> token = dingtalkService.getToken(tenant);
            if (token.getCode() == 0) {
                JsonResult<String> upload = dingtalkService.uploadFile(token.getData(), filePath, "file");
                if (upload.getCode() == 0) {
                    map.put("mediaId", upload.getData());
                    map.put("fileType", "xlsx");
                    map.put("fileName", filePath.substring(filePath.lastIndexOf('/') + 1));
                }
                return JSON.stringify(map);
            }
        } catch (Exception e) {
            log.error(e);
            throw new RuntimeException(e);
        }
        return null;
    }

    /**
     * 生成excel文件
     *
     * @param reports
     * @author 陈广煜
     * @date 2024-07-31
     */
    private String createExcel(List<DailyReport> reports) {
        List<DailyReportStatisticsExportModel> models = new ArrayList<>();
        for (DailyReport report : reports) {
            DailyReportStatisticsExportModel exportModel = new DailyReportStatisticsExportModel(report.getName(), report.getMon(), report.getTue(), report.getWed(), report.getThu(), report.getFri(), report.getSat(), report.getSun(), "");
            models.add(exportModel);
        }
        String templatePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("excel/日报统计.xlsx")).getPath();
        File file = new File("./excel");
        if (!file.exists()) {
            file.mkdir();
        }
        String excelPath = "./excel/日报统计" + D.convert2DateString(new Date()) + ".xlsx";
        //EasyExcel.write(excelPath, DailyReportStatisticsExportModel.class).withTemplate(templatePath)
        //        .excelType(ExcelTypeEnum.XLSX).head(new ArrayList<>()).sheet().doFill(models);
        ExcelWriter ew = EasyExcel.write(excelPath).withTemplate(templatePath).build();
        try {
            // 参数校验
            //validatePaths(templatePath, excelPath);
            WriteSheet build = EasyExcel.writerSheet().build();
            List<LocalDate> localDates = weekDate(LocalDate.now());
            // 使用更简洁的方式构建Map
            Map<Object, Object> map = MapUtil.builder()
                    .put("year", LocalDate.now().getYear())
                    .put("begin", LocalDateTimeUtil.format(localDates.get(0), "MM.dd"))
                    .put("end", LocalDateTimeUtil.format(localDates.get(6), "MM.dd"))
                    .put("tm", LocalDateTimeUtil.format(localDates.get(0), "yyyy-MM-dd"))
                    .put("tt", LocalDateTimeUtil.format(localDates.get(1), "yyyy-MM-dd"))
                    .put("tw", LocalDateTimeUtil.format(localDates.get(2), "yyyy-MM-dd"))
                    .put("ttu", LocalDateTimeUtil.format(localDates.get(3), "yyyy-MM-dd"))
                    .put("tf", LocalDateTimeUtil.format(localDates.get(4), "yyyy-MM-dd"))
                    .put("ts", LocalDateTimeUtil.format(localDates.get(5), "yyyy-MM-dd"))
                    .put("tsu", LocalDateTimeUtil.format(localDates.get(6), "yyyy-MM-dd"))
                    .build();
            FillConfig config = new FillConfig();
            config.setAutoStyle(true);
            //config.getForceNewRow();
            // 填充数据
            ew.fill(map, config, build);
            ew.fill(models, config, build);
            //ew.close();
        } catch (Exception e) {
            // 异常处理
            e.printStackTrace();
            log.error(e);
        } finally {
            ew.close();
        }
        return excelPath;
    }

    /**
     * 获取从本周一到本周日的日期列表。
     *
     * @param today 今天的日子，用于计算本周一的起始点。
     * @return 包含本周每一天的日期列表。
     */
    public List<LocalDate> weekDate(LocalDate today) {
        // 将今天调整到本周一，如果今天已经是周一，则不做调整。
        LocalDate mondayThisWeek = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));

        // 初始化一个列表，用于存储本周的每一天。
        List<LocalDate> datesOfThisWeek = new ArrayList<>();
        // 循环7天，从本周一开始，依次添加每一天的日期到列表中。
        for (int i = 0; i < 7; i++) {
            datesOfThisWeek.add(mondayThisWeek.plusDays(i));
        }
        // 返回包含本周每一天的日期列表。
        return datesOfThisWeek;
    }

    /**
     * 获取总经理和副总经理
     *
     * @return
     * @author 陈广煜
     * @date 2024-08-23
     */
    public List<String> getManager() {
        String tenantRootOrgId = iamOrgService.getTenantRootOrgId(IamSecurityUtils.getCurrentTenantId());
        if (!S.equals(tenantRootOrgId, ((IamUser) IamSecurityUtils.getCurrentUser()).getOrgId())) {
            return null;
        }
        QueryWrapper<IamUser> qw = new QueryWrapper<>();
        qw.lambda().select(IamUser::getId).eq(IamUser::getOrgId, tenantRootOrgId).ne(IamUser::getUserNum, "admin");
        List<IamUser> users = iamUserService.getEntityList(qw);
        return BeanUtils.collectToList(users, IamUser::getId);
    }

    /**
     * 销售趋势
     *
     * @param type 类型 y m d
     * @return
     */
    @Override
    public List<Map<String, Object>> salesTrends(String type) {
        LocalDate beginDate = beginDate(type);
        LocalDate endDate = LocalDate.now();
        // 获取时间范围内新增的销售合同
        SalesContractDTO dto = new SalesContractDTO().setCreateTimeBegin(beginDate).setCreateTimeEnd(endDate);
        dto.setPushStatus(1);
        List<SalesContract> contracts = salesContractService.getEntityList(QueryBuilder.toQueryWrapper(dto));
        // 获取时间范围内新增回款
        PaymentCertDTO paymentCertDTO = new PaymentCertDTO().setCreateTimeBegin(beginDate).setCreateTimeEnd(endDate);
        paymentCertDTO.setSapPushStatus(2);
        List<PaymentCertListVO> payments = Binder.convertAndBindRelations(paymentCertService.getEntityList(QueryBuilder.toQueryWrapper(paymentCertDTO)), PaymentCertListVO.class);
        if (S.equals(type, "y")) {
            return yearTrend(contracts, payments);
        } else if (S.equals(type, "m")) {
            return monthTrend(contracts, payments);
        } else {
            return dayTrend(contracts, payments);
        }
    }

    /**
     * 日趋势
     *
     * @param contracts
     * @param payments
     * @return
     */
    private List<Map<String, Object>> dayTrend(List<SalesContract> contracts, List<PaymentCertListVO> payments) {
        Map<Integer, List<SalesContract>> contractsGroupByHour = contracts.stream().collect(Collectors.groupingBy(e -> e.getCreateTime().getHour()));
        Map<Integer, List<PaymentCertListVO>> paymentsGroupByHour = payments.stream().collect(Collectors.groupingBy(e -> e.getCreateTime().getHour()));
        List<Map<String, Object>> result = new ArrayList<>();
        List<String> contractData = new ArrayList<>();
        for (int i = 0; i < 24; i++) {
            contractData.add(contractsGroupByHour.get(i) == null ? "0" : String.valueOf(contractsGroupByHour.get(i).stream().map(e -> new BigDecimal(e.getFixedDiscountAmount())).reduce(BigDecimal.ZERO, BigDecimal::add)));
        }
        Map<String, Object> contractMap = new HashMap<>();
        contractMap.put("name", "合同金额");
        contractMap.put("data", contractData);
        result.add(contractMap);
        Map<String, Object> paymentMap = new HashMap<>();
        List<String> paymentData = new ArrayList<>();
        for (int i = 0; i < 24; i++) {
            paymentData.add(paymentsGroupByHour.get(i) == null ? "0" : String.valueOf(paymentsGroupByHour.get(i).stream().map(e -> e.getPaymentRegister().getPaymentAmount()).reduce(BigDecimal.ZERO, BigDecimal::add)));
        }
        paymentMap.put("name", "回款金额");
        paymentMap.put("data", paymentData);
        result.add(paymentMap);
        return result;
    }

    private List<Map<String, Object>> monthTrend(List<SalesContract> contracts, List<PaymentCertListVO> payments) {
        Map<Integer, List<SalesContract>> contractsGroupByHour = contracts.stream().collect(Collectors.groupingBy(e -> e.getCreateTime().getDayOfMonth()));
        Map<Integer, List<PaymentCertListVO>> paymentsGroupByHour = payments.stream().collect(Collectors.groupingBy(e -> e.getCreateTime().getDayOfMonth()));
        List<Map<String, Object>> result = new ArrayList<>();
        List<String> contractData = new ArrayList<>();
        // 获取月份的天数
        int days = LocalDate.now().lengthOfMonth();
        for (int i = 1; i <= days; i++) {
            contractData.add(contractsGroupByHour.get(i) == null ? "0" : String.valueOf(contractsGroupByHour.get(i).stream().map(e -> new BigDecimal(e.getFixedDiscountAmount())).reduce(BigDecimal.ZERO, BigDecimal::add)));
        }
        Map<String, Object> contractMap = new HashMap<>();
        contractMap.put("name", "合同金额");
        contractMap.put("data", contractData);
        result.add(contractMap);
        Map<String, Object> paymentMap = new HashMap<>();
        List<String> paymentData = new ArrayList<>();
        for (int i = 1; i < days; i++) {
            paymentData.add(paymentsGroupByHour.get(i) == null ? "0" : String.valueOf(paymentsGroupByHour.get(i).stream().map(e -> e.getPaymentRegister().getPaymentAmount()).reduce(BigDecimal.ZERO, BigDecimal::add)));
        }
        paymentMap.put("name", "回款金额");
        paymentMap.put("data", paymentData);
        result.add(paymentMap);
        return result;
    }

    private List<Map<String, Object>> yearTrend(List<SalesContract> contracts, List<PaymentCertListVO> payments) {
        Map<Integer, List<SalesContract>> contractsGroupByHour = contracts.stream().collect(Collectors.groupingBy(e -> e.getCreateTime().getMonthValue()));
        Map<Integer, List<PaymentCertListVO>> paymentsGroupByHour = payments.stream().collect(Collectors.groupingBy(e -> e.getCreateTime().getMonthValue()));
        List<Map<String, Object>> result = new ArrayList<>();
        List<String> contractData = new ArrayList<>();
        for (int i = 1; i <= 12; i++) {
            contractData.add(contractsGroupByHour.get(i) == null ? "0" : String.valueOf(contractsGroupByHour.get(i).stream().map(e -> new BigDecimal(e.getFixedDiscountAmount())).reduce(BigDecimal.ZERO, BigDecimal::add)));
        }
        Map<String, Object> contractMap = new HashMap<>();
        contractMap.put("name", "合同金额");
        contractMap.put("data", contractData);
        result.add(contractMap);
        Map<String, Object> paymentMap = new HashMap<>();
        List<String> paymentData = new ArrayList<>();
        for (int i = 1; i <= 12; i++) {
            paymentData.add(paymentsGroupByHour.get(i) == null ? "0" : String.valueOf(paymentsGroupByHour.get(i).stream().map(e -> e.getPaymentRegister().getPaymentAmount()).reduce(BigDecimal.ZERO, BigDecimal::add)));
        }
        paymentMap.put("name", "回款金额");
        paymentMap.put("data", paymentData);
        result.add(paymentMap);
        return result;
    }

    /**
     * 销售漏斗
     *
     * @param type
     * @return
     */
    @Override
    public Object salesFunnels(String type) {
        LocalDate beginDate = beginDate(type);
        LocalDate endDate = LocalDate.now();
        // 获取时间范围内的商机
        BusinessDTO dto = new BusinessDTO().setCreateTimeBegin(beginDate).setCreateTimeEnd(endDate);
        List<Business> businessList = businessMapper.selectList(QueryBuilder.toQueryWrapper(dto));
        Map<String, Long> map = new HashMap<>();
        if (businessList != null && !businessList.isEmpty()) {
            long win = businessList.stream().filter(e -> S.equals(e.getWinType(), "win")).count();
            long lose = businessList.stream().filter(e -> S.equals(e.getWinType(), "lose")).count();
            map.put("win", win);
            map.put("lose", lose);
        } else {
            map.put("win", 0L);
            map.put("lose", 0L);
        }
        return map;
    }
}
